home *** CD-ROM | disk | FTP | other *** search
- /*
- Commodore 64 Emulator v0.1 Earle F. Philhower III
- Copyright (C) 1993-4 (st916w9r@dunx1.ocs.drexel.edu)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include "Vectors.h"
- #include "Flags.h"
- #include "Registers.h"
- #include "Memory.h"
- #include "Modes.h"
- #include "Stack.h"
- #include "Keyboard.h"
- #include <AppleEvents.h>
-
- extern WindowPtr VICWind;
- extern Cursor commie;
- extern void (* instruct[256]) ();
- extern byte cycletime[256];
- extern int missingROM;
-
- #define kWindowStrings 500
- enum { kRunningWindow=1, kSuspendedWindow };
-
- byte interruptProcessor;
- static byte numLeftSameChar;
- static void ProcessPerLine(void);
- extern void ProcessorLoop(void);
-
- void ProcessorLoop()
- {
- int scanLines, vicCalls;
- byte instructCode, oldMemoryMap, processorCycles, col;
- byte *dc01, *dc00, *d012, *d011, *d018;
- Str255 str;
- unsigned long tempa1, tempa2, tempd1, tempd2;
- byte **localMemory;
-
- /* Set up window, cursor for running state */
- GetIndString(str, kWindowStrings, kRunningWindow);
- SetWTitle(VICWind, str);
- SetCursor(&commie);
- ObscureCursor();
-
- /* Initialize precomputed addresses (minimal speed gain) */
- dc00=&RAM[0xdc00];
- dc01=&RAM[0xdc01];
- d012=&RAM[0xd012];
- d011=&RAM[0xd011];
- d018=&RAM[0xd018];
-
- /* Set up the memory dereferences, and store current map */
- oldMemoryMap=*RAMp1;
- SetUpMemoryMap();
-
- /* Some flags and counters necessray to be initialized */
- interruptProcessor=0;
- numLeftSameChar=0;
- processorCycles=0;
- scanLines=0;
- vicCalls=0;
-
- while (interruptProcessor==0) {
- tempd2=pc;
- asm {
- move.l a1, tempa1
- move.l d1, tempd1
- move.l tempd2, d1
-
- move.l memory, a1
- lsl.l #2, d1
- move.l (a1, d1.l), a1
- move.b (a1), instructCode
-
- move.l tempd1, d1
- move.l tempa1, a1
- };
-
- /*instructCode = ImmediateByte();*/ pc++;
- processorCycles += cycletime[instructCode];
- (*instruct[instructCode])();
-
- /* Set up the memory map if it has changed */
- if (*RAMp1!=oldMemoryMap) {
- SetUpMemoryMap();
- oldMemoryMap=*RAMp1; }
-
- /* If we've done 35 cycles, we've gone through 1 scanline */
- if (processorCycles>35) {
- processorCycles=0;
-
- /* Update the current VIC scan register */
- if (++*d012==0) *d011 ^= 128;
- *d018 |=1;
-
- /* If we've gone through 350 lines, we've due for an interrupt */
- if (++scanLines>350) {
- scanLines=0;
-
- /* Set raster to 0 line */
- *d012=0;
- *d011&=127;
-
- /* Currently we just update the keyboard registers */
- ProcessPerLine();
- if (++vicCalls==2) {
- RedrawVIC();
- vicCalls=0; }
-
- /* Call interrupt routine if interrupts enabled */
- if ((flags&INT)==0) {
- PushWord(pc);
- Push(flags);
- pc=WordAt(IrqTo);
- }
- }
- }
-
- /* Set up the keyboard register according to precomputed values */
- *dc01=scanCode[*dc00];
- }
-
- /* Done processing, reset window, cursor */
- RedrawVIC();
- SetCursor(&qd.arrow);
- GetIndString(str, kWindowStrings, kSuspendedWindow);
- SetWTitle(VICWind, str);
- }
-
- /* Called once per scanline, currently check for keypress or mouse button */
- static void ProcessPerLine()
- {
- EventRecord evt;
- int x;
- char theChar;
-
- /* We keep the same keyboard map for 1/30th of a second */
- if (numLeftSameChar==0) {
- numLeftSameChar=2;
-
- /* Check for any key or mouse press */
- if (GetNextEvent(-1, &evt)!=false)
- switch(evt.what) {
- /* A mouseclick stops our simulation */
- case mouseDown: MiniHandleMouseDown(evt); break;
- case updateEvt:
- BeginUpdate((WindowPtr)evt.message);
- EndUpdate((WindowPtr)evt.message); break;
- case app4Evt:
- if (evt.message&1);
- else interruptProcessor=1;
- break;
- case kHighLevelEvent :
- AEProcessAppleEvent(&evt); break;
- /* A keypress is simulated by fudging the CIA registers */
- case keyDown: case autoKey:
- theChar = evt.message&charCodeMask;
- if ((evt.modifiers&cmdKey)!=0)
- DoMenuChoice(MenuKey(theChar));
- else {
- AppleScanKeyboard(evt.message&charCodeMask, evt.modifiers);
- SetupScanCodes();}
- }
-
- /* No keypress, so clear out keyboard register fudge */
- else { for (x=0; x<256; x++) scanCode[x]=0xff; SystemTask(); }
- }
- else numLeftSameChar--;
- }
-
- #define ALIGNBYTE
-
- MiniHandleMouseDown(event)
- EventRecord event;
- {
- WindowPtr theWind;
- GrafPtr gp;
- Point x;
- short thePart;
- extern Rect dragRect;
-
- thePart=FindWindow(event.where, &theWind);
- switch(thePart) {
- case inSysWindow: SystemClick(&event, theWind); interruptProcessor=1; break;
- case inDrag:
- DragWindow(theWind, event.where, &dragRect);
- #ifdef ALIGNBYTE
- GetPort(&gp);
- SetPort(theWind);
- x.h=x.v=0;
- LocalToGlobal(&x);
- x.h&=0xfff8;
- MoveWindow(theWind, x.h, x.v, TRUE);
- SetPort(gp);
- #endif
- break;
- case inMenuBar: DoMenuChoice(MenuSelect(event.where)); break;
- case inContent: interruptProcessor=1; break;
- }
- }
-